#pragma once
#include "requestor.hpp"

namespace BRpc
{
    namespace Client
    {
        class RpcCaller
        {
        public:
            using ptr = std::shared_ptr<RpcCaller>;
            using JsonAsyncResponse = std::future<Json::Value>;
            using JsonResponseCallBack = std::function<void(const Json::Value &)>;
        public:
            RpcCaller(Requestor::ptr requestor):_requestor(requestor){}

            bool call(const BaseConnection::ptr &conn, const std::string method,
                      const Json::Value &params, Json::Value &result)
            {
                // 组织请求
                auto request_msg = MessageFactory::create<RpcRequest>();
                request_msg->setId(UUID::uuid());
                request_msg->setMethod(method);
                request_msg->setMType(BRpc::MType::REQ_RPC);
                request_msg->setParam(params);
                // 发送请求
                BaseMessage::ptr rsp;
                DLOG("发送请求");
                auto ret = _requestor->send(conn, request_msg, rsp);
                if (ret == false)
                {
                    ELOG("同步Rpc请求失败！");
                    return false;
                }
                // 等待响应
                auto rsp_msg = std::dynamic_pointer_cast<RpcResponse>(rsp);
                if (rsp_msg == nullptr)
                {
                    ELOG("rpc响应，向下类型转换失败！");
                    return false;
                }
                if (rsp_msg->rcode() != RCode::RCODE_OK)
                {
                    ELOG("rpc请求出错:%s", errReason(rsp_msg->rcode()));
                    std::cout<<"rpc请求出错:"<<errReason(rsp_msg->rcode());
                    return false;
                }
                result = rsp_msg->result();
                return true;
            }
            bool call(const BaseConnection::ptr &conn, const std::string method,
                      const Json::Value &params, JsonAsyncResponse &result)
            {
                // 组织请求
                auto request_msg = MessageFactory::create<RpcRequest>();
                request_msg->setId(UUID::uuid());
                request_msg->setMethod(method);
                request_msg->setMType(BRpc::MType::REQ_RPC);
                request_msg->setParam(params);
                // 发送请求
                auto rsp_promise = std::make_shared<std::promise<Json::Value>>();
                result = rsp_promise->get_future();
                Requestor::RequestCallBack cb = std::bind(&RpcCaller::CallBack, this, rsp_promise, std::placeholders::_1);
                auto ret = _requestor->send(conn, request_msg, cb);
                if (ret == false)
                {
                    ELOG("异步Rpc请求失败！");
                    return false;
                }
                return true;
            }
            bool call(const BaseConnection::ptr &conn, const std::string method,
                      const Json::Value &params, const JsonResponseCallBack &cb)
            {
                 auto request_msg = MessageFactory::create<RpcRequest>();
                request_msg->setId(UUID::uuid());
                request_msg->setMethod(method);
                request_msg->setMType(BRpc::MType::REQ_RPC);
                request_msg->setParam(params);
                //发送请求
                Requestor::RequestCallBack req_cb= std::bind(&RpcCaller::CallBack1, this, cb, std::placeholders::_1);
                  bool ret = _requestor->send(conn, request_msg, req_cb);
                    if (ret == false) {
                        ELOG("回调Rpc请求失败！");
                        return false;
                    }
                    return true;
            }
            //有CallBack是因为requestor不仅仅是为了rpc请求服务 他为各种信息服务 所以参数是BaseMessage
            //我们为了能解决rpc请求 额外封装一层回调函数从而可以处理我们的rpc请求
        private:
            //回调处理结果的回调函数
             void CallBack1(const JsonResponseCallBack &cb, const BaseMessage::ptr &msg)
            {
                auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
                if (!rpc_rsp_msg)
                {
                    ELOG("rpc响应，向下类型转换失败！");
                    return;
                }
                if (rpc_rsp_msg->rcode() != RCode::RCODE_OK)
                {
                    ELOG("rpc异步请求出错：%s", errReason(rpc_rsp_msg->rcode()));
                    return;
                }
                cb(rpc_rsp_msg->result());
            }
            //异步处理结果的回调函数
            void CallBack(std::shared_ptr<std::promise<Json::Value>> result, const BaseMessage::ptr &msg)
            {
                auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
                if (!rpc_rsp_msg)
                {
                    ELOG("rpc响应，向下类型转换失败！");
                    return;
                }
                if (rpc_rsp_msg->rcode() != RCode::RCODE_OK)
                {
                    ELOG("rpc异步请求出错：%s", errReason(rpc_rsp_msg->rcode()));
                    return;
                }
                result->set_value(rpc_rsp_msg->result());
            }

        private:
            Requestor::ptr _requestor;
        };
    }
}